﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.IO;
using System.IO.IsolatedStorage;

namespace PhoneApp1
{
    // Stores a single vote to be sent over relay service
    [DataContract]
    public class Vote
    {
        [DataMember]
        public User voter;

        [DataMember]
        public Guid pollGuid;

        [DataMember]
        public Guid choiceGuid;

        public Vote()
        {
            voter = new User();
        }

        public Vote(User voter, Poll p, Choice c)
        {
            this.voter = voter;
            pollGuid = p.guid;
            choiceGuid = c.guid;
        }

        public void Serialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            ser.WriteObject(streamObject, this);
        }

        public void Deserialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            Vote v = (Vote)ser.ReadObject(streamObject);
            this.voter = v.voter;
            this.pollGuid = v.pollGuid;
            this.choiceGuid = v.choiceGuid;
            return;
        }

        public byte[] getBytes()
        {
            MemoryStream ms = new MemoryStream();
            Serialize(ms);
            ms.Position = 0;
            return ms.ToArray();
        }
        public void setBytes(byte[] b)
        {
            MemoryStream ms = new MemoryStream();
            ms.Write(b, 0, b.Length);
            ms.Position = 0;
            Deserialize(ms);
            ms.Close();
        }
   
    }

    // Possible messages to recieve:
    public enum PollAppMessageType {newPoll, newVote};

    /* Class Message: stores anything to be sent over the relay service */
    [DataContract]
    public class PollAppMessage
    {
        [DataMember]
        public User sender;

        [DataMember]
        public PollAppMessageType type;

        [DataMember]
        public byte[] data;

        public PollAppMessage()
        {
            sender = new User();
        }

        public void Serialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            ser.WriteObject(streamObject, this);
        }

        public void Deserialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            PollAppMessage m = (PollAppMessage)ser.ReadObject(streamObject);
            this.sender = m.sender;
            this.data = m.data;
            this.type = m.type;
            return;
        }

        public byte[] getBytes()
        {
            MemoryStream ms = new MemoryStream();
            Serialize(ms);
            ms.Position = 0;
            return ms.ToArray();
        }
        public void setBytes(byte[] b)
        {
            MemoryStream ms = new MemoryStream();
            ms.Write(b, 0, b.Length);
            ms.Position = 0;
            Deserialize(ms);
            ms.Close();
        }
    }

    /* Class User: stores a single user */
    [DataContract]
    public class User
    {
        [DataMember]
        public string name;

        [DataMember]
        public Guid guid;

        public User()
        {
            this.name = "";
            this.guid = Guid.NewGuid();
        }
        public User(string name)
        {
            this.name = name;
            this.guid = Guid.NewGuid();
        }

        public void Change_Name(string name)
        {
            this.name = name;
        }


    }


    /* Class Choice: stores a choice possible in a Poll */
    [DataContract]
    public class Choice
    {
        [DataMember]
        public string choiceText { get; set; }

        [DataMember]
        public int votes;

        [DataMember]
        public List<User> voters;

        [DataMember]
        public Guid guid;

        public Choice()
        {
            choiceText = "";
            votes = 0;
            guid = Guid.NewGuid();
            voters = new List<User>();
        }
        public Choice(string question)
        {
            this.choiceText = question;
            votes = 0;
            guid = Guid.NewGuid();
            voters = new List<User>();
        }

    }

    /* Class Poll: stores a poll */
    [DataContract]
    public class Poll
    {
        [DataMember]
        public string pollName { get; set; }

        [DataMember]
        public string questionText { get; set; }

        [DataMember]
        public List<Choice> choices;

        [DataMember]
        public User creator;

        [DataMember]
        public Guid guid;

        public Poll()
        {
            guid = Guid.NewGuid();
            choices = new List<Choice>();
            creator = new User();
        }

        public void Serialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            ser.WriteObject(streamObject, this);
        }

        public void Deserialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            Poll p = (Poll)ser.ReadObject(streamObject);
            this.questionText = p.questionText;
            this.pollName = p.pollName;
            this.guid = p.guid;
            this.creator = p.creator;
            this.choices = p.choices;
            return;
        }

        public byte[] getBytes()
        {
            MemoryStream ms = new MemoryStream();
            Serialize(ms);
            ms.Position = 0;
            return ms.ToArray();
        }
        public void setBytes(byte[] b)
        {
            MemoryStream ms = new MemoryStream();
            ms.Write(b, 0, b.Length);
            ms.Position = 0;
            Deserialize(ms);
            ms.Close();
        }
    }

    /* Class DataFile: stores everything that will be read/written to file 
     * (add whatever you want here for persistent settings, etc) */
    [DataContract]
    public class DataFile
    {
        [DataMember]
        public List<Poll> polls;

        [DataMember]
        public List<string> created_groups;

        [DataMember]
        public User login;

        [DataMember]
        public string otherdatahere;

        public void Serialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            ser.WriteObject(streamObject, this);
        }

        public void Deserialize(Stream streamObject)
        {
            if (streamObject == null)
                return;

            DataContractSerializer ser = new DataContractSerializer(this.GetType());
            DataFile df = (DataFile)ser.ReadObject(streamObject);
            this.polls = df.polls;
            this.otherdatahere = df.otherdatahere;
            this.login = df.login;
            this.created_groups = df.created_groups;

            return;
        }

        public DataFile()
        {
            this.polls = new List<Poll>();
            this.login = new User();
            this.created_groups = new List<string>();
            
        }
    }

    /* Class FileStorage: Handles the reading and writing to file
     * Contains the DataFile (see above)*/
    public class FileStorage
    {
        public DataFile df;

        public void LoadFile()
        {
            using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream file = appStorage.OpenFile("datafile.dat", FileMode.OpenOrCreate))
                {
                    try
                    {
                        df.Deserialize(file);
                    }
                    catch { }

                }
            }
            // TODO: delete this (its just here for debugging)
            if (df.polls.Count == 0)
            {
                Poll p = new Poll();
                p.questionText = "How much wood can a woodchuck chuck?";
                p.pollName = "Woodchuck";
                p.creator = new User("Doug");
                p.choices.Add(new Choice("1"));
                p.choices.Add(new Choice("2"));
                p.choices.Add(new Choice("3"));
                p.choices.Add(new Choice("4"));
                df.polls.Add(p);
            }
        }

        public void WriteFile()
        {
            using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream file = appStorage.OpenFile("datafile.dat", FileMode.OpenOrCreate))
                {
                    try
                    {
                        df.Serialize(file);
                    }
                    catch { }

                }
            } 
        }

        public FileStorage() 
        {
            df = new DataFile();
        } 
    }
}
